import java.awt.Point;
import java.util.ArrayList;

/**
 * The class object retains list of words as array of Word object. It also
 * provide functions to access and manipulate word list.
 * 
 * 
 * @Function_prototypes: public void clear() public void addWord (String word)
 *                       public void addWord (String word, Point[] location)
 *                       public void setLocation (int index, Point[] location)
 *                       public void setLocation (String word, Point[] location)
 *                       public ArrayList<Word> getWordList() public String[]
 *                       getWords () public String getWord (int index) public
 *                       Point[] getLocation (int index) public Point[]
 *                       getLocation (String word) public void removeWord
 *                       (String word) public void removeWord (int index) public
 *                       void sortByLength () private void swap (Word word1,
 *                       Word word2) private int findWordIndex (String word)
 * 
 * @author Hardik
 * 
 */
public class WordList implements Cloneable {

	private ArrayList<Word> wordList;

	/**
	 * A function create WordList object with assigning wordList instance
	 * variable to ArryList of Word object
	 */
	public WordList() {
		// TODO Auto-generated constructor stub
		wordList = new ArrayList<Word>();
	}

	/**
	 * A function clear out the wordList
	 */
	public void clear() {
		wordList = new ArrayList<Word>();
	}

	/**
	 * A function insert the word if it doesn't exist in word list and doesn't
	 * contain any other characters than alphabetical letters
	 * 
	 * @param word
	 *            to add
	 * 
	 * @throws exception
	 *             if word contain anything other than letters
	 * @throws exception
	 *             if word is already exist in wordList
	 */
	public void addWord(String word) throws Exception {
		word = word.toUpperCase();

		// check to see if word contains only letters or not
		for (int i = 0; i < word.length(); i++) {
			if (!Character.isLetter(word.charAt(i))) {
				throw new Exception("Your word contains an invalid character!");
			}
		}

		// check whether word is already in wordList or not
		if (findWordIndex(word) != -1) {
			throw new Exception("Duplicate word found!");
		}
		wordList.add(new Word(word));
	}

	/**
	 * A function insert the word with location if it doesn't exist in word list
	 * and doesn't contain any other characters than alphabetical letters
	 * 
	 * @param word
	 *            to add
	 * @param location
	 *            of the word
	 * @throws exception
	 *             if word contain anything other than letters
	 * @throws exception
	 *             if word is already exist in wordList
	 */
	public void addWord(String word, Point[] location) throws Exception {
		word = word.toUpperCase();

		// check to see if word contains only letters or not
		for (int i = 0; i < word.length(); i++) {
			if (!Character.isLetter(word.charAt(i))) {
				throw new Exception("Your word contains an invalid character!");
			}
		}

		// check whether word is already in wordList or not
		if (findWordIndex(word) != -1) {
			throw new Exception("Duplicate word found!");
		}
		wordList.add(new Word(word, location));
	}

	/**
	 * set location of word at given index
	 * 
	 * @param index
	 *            of the word
	 * @param location
	 *            of the word to set
	 */
	public void setLocation(int index, Point[] location) {
		wordList.get(index).setLocation(location);
	}

	/**
	 * set the location of word
	 * 
	 * @param word
	 *            to set the location of
	 * @param location
	 *            of the word to set
	 */
	public void setLocation(String word, Point[] location) {
		word = word.toUpperCase();
		int wordPosition = findWordIndex(word);
		if (wordPosition != -1) {
			wordList.get(wordPosition).setLocation(location);
		}
	}

	/**
	 * A function gives clone or copy of word list that object contain
	 * 
	 * @return wordList clone
	 */
	public ArrayList<Word> getWordList() {
		ArrayList<Word> newWordList = new ArrayList<Word>();
		for (int i = 0; i < newWordList.size(); i++) {
			Word wordCopy = (Word) (wordList.get(i).clone());
			newWordList.add(wordCopy);
		}
		return (newWordList);
	}

	/**
	 * give string word at given position of wordList
	 * 
	 * @param index
	 *            of word
	 * @return word of string form
	 */
	public String getWord(int index) {
		return ((wordList.get(index)).getWord());
	}

	/**
	 * gives array of string words by separating words from Word object, that
	 * also contain location of words
	 * 
	 * @return words in format of array of string
	 */
	public String[] getWords() {
		String[] words = new String[wordList.size()];
		for (int i = 0; i < wordList.size(); i++) {
			words[i] = wordList.get(i).getWord();
		}
		return (words);
	}

	/**
	 * A function gives number of words that WordList object contains
	 * 
	 * @return number of words in WordList object
	 */
	public int getWordCount() {
		return (wordList.size());
	}

	/**
	 * gives location of a word in array of points formation based on position
	 * of word
	 * 
	 * @param index
	 *            of word
	 * @return location of word in form of array of points
	 */
	public Point[] getLocation(int index) {
		return (wordList.get(index).getLocation());
	}

	/**
	 * gives location of a word in array of points formation based on word
	 * itself
	 * 
	 * @param word
	 *            to look for position in wordList
	 * @return location of the given word
	 */
	public Point[] getLocation(String word) {
		word = word.toUpperCase();
		int wordPosition = findWordIndex(word);
		if (wordPosition != -1) {// word exist in list
			return (wordList.get(wordPosition).getLocation());
		}
		return null;
	}

	/**
	 * remove given word from the wordList
	 * 
	 * @param word
	 *            to remove from the list
	 */
	public void removeWord(String word) {
		word = word.toUpperCase();
		int wordPosition = findWordIndex(word);
		if (wordPosition != -1) {// word exist in list
			wordList.remove(word);
		}
	}

	/**
	 * remove word from list at given position
	 * 
	 * @param index
	 *            of word
	 */
	public void removeWord(int index) {
		wordList.remove(index);
	}

	/**
	 * sort (selection sort) the word list by length of each Word
	 */
	public void sortByLength() {
		int max = wordList.size();
		while (max > 1) {
			Word small = wordList.get(0);
			Word last = wordList.get(max - 1);
			for (int index = 1; index < max; index++) {
				Word word2 = wordList.get(index);
				// if small word bigger than other word in list
				if (small.getWord().length() > word2.getWord().length()) {
					small = word2;
				}
			}
			if (small != last) { // if small word isn't last word
				swap(small, last);
			}
			max--;
		}
	}

	/**
	 * swap two Word object
	 * 
	 * @param word1
	 * @param word2
	 */
	private void swap(Word word1, Word word2) {
		int index1 = wordList.indexOf(word1);
		int index2 = wordList.indexOf(word2);
		wordList.set(index1, word2);
		wordList.set(index2, word1);
	}

	/**
	 * find index of the given word from the list if word exist in list
	 * otherwise returns -1 if there is no such index.
	 * 
	 * @param word
	 *            to find in list
	 * @return index of word
	 */
	private int findWordIndex(String word) {
		int index = -1;
		for (int i = 0; i < wordList.size(); i++) {
			if (wordList.get(i).getWord().equals(word)) {
				index = i;
				break;
			}
		}
		return (index);
	}
}
